//
// Created by wyh on 2025-07-13 21:00.
//

#include <sstream>
#include <fstream>
#include <xml/parser.h>
#include "xml/xml.h"

using namespace std;
using namespace wyh::xml;
using namespace wyh::utility;


Xml::Xml(const char *name) : m_name(name)
{

}

Xml::Xml(const std::string &name) : m_name(name)
{

}

Xml::Xml(const Xml &other)
{
    copy(other);
}

Xml::Xml(Xml &&other)
{
    swap(other);
}

Xml::~Xml()
{
    clear();
}

string Xml::name() const
{
    return m_name;
}

void Xml::name(const string &name)
{
    m_name = name;
}

string Xml::text() const
{
    return m_text;
}

void Xml::text(const string &text)
{
    m_text = text;
}

Value &Xml::attr(const string &key)
{
    return m_attrs[key];
}

void Xml::attr(const string &key, const Value &value)
{
    m_attrs[key] = value;
}

void Xml::append(const Xml &child)
{
    m_childs.push_back(child);
}

void Xml::append(Xml &&child)
{
    m_childs.push_back(std::move(child));
}

void Xml::remove(int index)
{
    if (m_childs.empty())
    {
        return;
    }

    int size = (int) m_childs.size();
    if (index < 0 || index >= size)
    {
        return;
    }

    m_childs.erase(m_childs.begin() + index);
}

void Xml::remove(const char *name)
{
    for (auto it = m_childs.begin(); it != m_childs.end();)
    {
        if (it->name() == name)
        {
            it = m_childs.erase(it);//返回删除元素下一位置的元素迭代器
        }
        else
        {
            ++it;
        }
    }
}

void Xml::remove(const string &name)
{
    remove(name.c_str());
}

Xml &Xml::operator[](int index)
{
    return m_childs.at(index);
}

Xml &Xml::operator[](const char *name)
{
    for (auto &m_child: m_childs)
    {
        if (m_child.name() == name)
        {
            return m_child;
        }
    }

    m_childs.emplace_back(name);
    return m_childs.back();
}

Xml &Xml::operator[](const string &name)
{
    return (*this)[name.c_str()];
}

Xml &Xml::operator=(const Xml &other)
{
    if (this == &other)
    {
        return *this;
    }

    copy(other);
    return *this;
}

Xml &Xml::operator=(Xml &&other) noexcept
{
    if (this == &other)
    {
        return *this;
    }

    swap(other);
    return *this;
}

int Xml::size() const
{
    return m_childs.size();
}

bool Xml::empty() const
{
    return m_childs.empty();
}

void Xml::clear()
{
    m_name.clear();
    m_text.clear();
    m_attrs.clear();
    m_childs.clear();
}

std::string Xml::str() const
{
    if (m_name.empty())
    {
        return "";
    }

    ostringstream oss;
    oss << "<";
    oss << m_name;

    for (auto attr: m_attrs)
    {
        oss << " " << attr.first << "=" << "\"" << attr.second << "\"";
    }
    oss << ">";

    for (auto child: m_childs)
    {
        oss << child.str();
    }

    oss << m_text;
    oss << "</" << m_name << ">";

    return oss.str();
}

void Xml::copy(const Xml &other)
{
    clear();
    m_name = other.m_name;
    m_text = other.m_text;
    m_attrs = other.m_attrs;
    m_childs = other.m_childs;
}

void Xml::swap(Xml &other)
{
    clear();
    m_name.swap(other.m_name);
    m_text.swap(other.m_text);
    m_attrs.swap(other.m_attrs);
    m_childs.swap(other.m_childs);
}

bool Xml::load(const string &filename)
{
    Parser p;
    if (!p.load(filename))
    {
        return false;
    }

    *this = p.parse();

    return false;
}

bool Xml::load(const char *buf, int len)
{
    Parser p;
    if (!p.load(buf,len))
    {
        return false;
    }

    *this = p.parse();

    return false;
}

bool Xml::save(const string &filename)
{
    std::ofstream ofs(filename);
    if (ofs.fail())
    {
        return false;
    }

    ofs << str();
    ofs.close();

    return true;
}
